/**
 * Created By xiyuan
 * Author server@xiyuan.name (惜缘叛逆)
 * DateTime 2019/3/28 18:28
 * Describe javascript功能
 * MIT License http://www.opensource.org/licenses/mit-license.php
 */

// 文件工具
const fs = require('fs');
// 路径包
const path = require('path');
// 逐行的方式读取数据流
const readline = require('readline');
// 工具
const {createLog} = require('./utils');

// 日志监听
function watch(logPath, callback) {
	
	if (fs.existsSync(logPath)) {
		// 获取文件内容大小
		const sizeCount = fs.statSync(logPath).size;
		// 日志文件监听
		watchFile(logPath, function () {
			callback(sizeCount)
		});
	} else {
		// 目录监听
		fs.watch(path.parse(logPath).dir, {encoding: 'utf-8'}, function (eventType, filename) {
			// 检查是否需要监听的文件发送变化
			if (path.parse(logPath).base !== filename) return;
			// 检查文件是否有内容
			if (fs.statSync(logPath).size) {
				callback()
			} else {
				// 日志文件监听
				watchFile(logPath, function () {
					callback();
				});
			}
			this.close();
		})
	}
}

// 文件监听
function watchFile(logPath, callback) {
	let timer;
	fs.watchFile(logPath, {encoding: 'utf-8'}, () => {
		clearTimeout(timer)
		// 避免文件持续写入导致重复调用文件读取
		timer = setTimeout(function () {
			callback()
		}, 100)
	});
}

// 内容解析
function textParse(str) {
	const res = str.match(/^([\d\/\s:]+?)\s+\[([\w+])\]\s+\[([\w:\.]+)\]\s+([\s\S]+)$/) || [];
	
	const msg= res[4];
	const date= res[1];
	const type= res[2];
	const codeFile= res[3];
	
	return {
		msg,
		date,
		type,
		codeFile,
	}
}


// 日志解析
class logParseClass {
	constructor(logPath) {
		this.logPath = logPath;
		// 事件记录器
		this.eventMap = {
			info: [],
			warn: [],
			error: [],
		};
		// 起始位置
		this.startSize = 0;
		// 清空日志文件
		if (fs.existsSync(logPath)) {
			fs.writeFileSync(logPath, "")
		}
		// 日志监听
		watch(logPath, size => {
			// 避免传入的行数小于之前的行数
			let startSize = size && this.startSize > size ? this.startSize : size || this.startSize;
			try {
				// 文件内容大小
				let fileSize = fs.statSync(logPath).size;
				// 日志文件解析
				this.fileParse(startSize, fileSize);
				// 设置最新的起始位置
				this.startSize = fileSize;
			}
			
			catch (e) {
				// 触发错误回调
				this.eventMap.error.forEach(fn => fn(createLog(e)));
			}
		})
	}
	
	// 日志文件解析
	fileParse(start, end) {
		// 检查范围段
		if (start == end) return this;
		// 文件路径
		const filePath = this.logPath;
		
		// 逐行读取
		const read = readline.createInterface({
			// 获取文件中指定位置的内容
			input: fs.createReadStream(filePath, {start, end})
		});
		
		// 行数读取
		read.on('line', content => {
			// 日志内容
			content = textParse(content);
			// 检查日志类型
			switch (content.type) {
				case 'I':
					// 触发常规信息回调
					this.eventMap.info.forEach(fn => fn(content));
					break;
				case 'W':
					// 触发警告回调
					this.eventMap.warn.forEach(fn => fn(content));
					break;
				case 'E':
					// 触发错误回调
					this.eventMap.error.forEach(fn => fn(content));
					break;
			}
			
		});
		return this;
	}
	
	// 监听常规信息
	watchInfo(fn) {
		// 事件记录
		this.eventMap.info.push(fn);
		return this;
	}
	
	// 监听警告信息
	watchWarn(fn) {
		// 事件记录
		this.eventMap.warn.push(fn);
		return this;
	}
	
	// 监听错误信息
	watchError(fn) {
		// 事件记录
		this.eventMap.error.push(fn);
		return this;
	}
	
	
}

module.exports = function (logPath) {
	return new logParseClass(logPath)
}